<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>狮子座</title>
    <link rel="icon" href="https://img.kaikeba.com/kkb_portal_icon.ico" />
    <style>
      body {
        margin: 0;
        overflow: hidden;
      }

      #canvas {
        background: url('./images/sky.jpg');
        background-size: cover;
        background-position: right bottom;
      }

      #audio {
        position: absolute;
        right: 20px;
        bottom: 20px;
        opacity: 10%;
        transition: opacity 200ms;
        z-index: 20;
      }

      #audio:hover {
        opacity: 90%;
      }
    </style>
  </head>

  <body>
    <canvas id="canvas"></canvas>
    <audio id="audio" controls loop autoplay>
      <source src="./audio/szz.mp3" type="audio/mpeg" />
    </audio>
    <!-- 顶点着色器 -->
    <script id="vertexShader" type="x-shader/x-vertex">
      attribute vec4 a_Attr;
      varying float v_Alpha;
      void main(){
          gl_Position=vec4(a_Attr.x,a_Attr.y,0.0,1.0);
          gl_PointSize=a_Attr.z;
          v_Alpha=a_Attr.w;
      }
    </script>
    <!-- 片元着色器 -->
    <script id="fragmentShader" type="x-shader/x-fragment">
      precision mediump float;
      uniform bool u_IsPOINTS;
      varying float v_Alpha;
      void main(){
        if(u_IsPOINTS){
          float dist=distance(gl_PointCoord,vec2(0.5,0.5));
          if(dist<0.5){
            gl_FragColor=vec4(0.87,0.91,1,v_Alpha);
          }else{
            discard;
          }
        }else{
          gl_FragColor=vec4(0.87,0.91,1,v_Alpha);
        }
      }
    </script>
    <script type="module">
      import {
        initShaders,
        getMousePosInWebgl,
        glToCssPos,
      } from '../jsm/Utils.js'
      import Poly from '../jsm/Poly.js'
      import Sky from '../jsm/Sky.js'
      import Compose from '../jsm/Compose.js'
      import Track from '../jsm/Track.js'

      const canvas = document.querySelector('#canvas')
      canvas.width = window.innerWidth
      canvas.height = window.innerHeight

      // 获取着色器文本
      const vsSource = document.querySelector('#vertexShader').innerText
      const fsSource = document.querySelector('#fragmentShader').innerText

      //三维画笔
      const gl = canvas.getContext('webgl')
      gl.enable(gl.BLEND)
      gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

      //初始化着色器
      initShaders(gl, vsSource, fsSource)

      //声明颜色 rgba
      gl.clearColor(0, 0, 0, 0)
      //刷底色
      gl.clear(gl.COLOR_BUFFER_BIT)

      //夜空
      const sky = new Sky(gl)
      //建立合成对象
      const compose = new Compose()

      //正在绘制的多边形
      let poly = null
      //鼠标划上的点
      let point = null

      //取消右击提示
      canvas.oncontextmenu = function () {
        return false
      }

      canvas.addEventListener('mousedown', (event) => {
        if (event.button === 2) {
          // 鼠标右击事件
          popVertice()
        } else {
          // 鼠标左击事件
          const { x, y } = getMousePosInWebgl(event, canvas)
          if (poly) {
            addVertice(x, y)
          } else {
            crtPoly(x, y)
          }
        }
        render()
      })

      canvas.addEventListener('mousemove', (event) => {
        const { x, y } = getMousePosInWebgl(event, canvas)
        point = hoverPoint(x, y)
        canvas.style.cursor = point ? 'pointer' : 'default'
        if (poly) {
          const obj = poly.geoData[poly.geoData.length - 1]
          obj.x = x
          obj.y = y
        }
      })

      !(function ani() {
        compose.update(new Date())
        sky.updateVertices(['x', 'y', 'pointSize', 'alpha'])
        render()
        requestAnimationFrame(ani)
      })()

      function crtPoly(x, y) {
        let o1 = point ? point : { x, y, pointSize: random(), alpha: 1 }
        const o2 = { x, y, pointSize: random(), alpha: 1 }
        poly = new Poly({
          size: 4,
          attrName: 'a_Attr',
          geoData: [o1, o2],
          types: ['POINTS', 'LINE_STRIP'],
          circleDot: true,
        })
        sky.add(poly)
        crtTrack(o1)
        crtTrack(o2)
      }

      function addVertice(x, y) {
        const { geoData } = poly
        if (point) {
          geoData[geoData.length - 1] = point
        }
        let obj = { x, y, pointSize: random(), alpha: 1 }
        geoData.push(obj)
        crtTrack(obj)
      }

      function popVertice() {
        poly.geoData.pop()
        const { children } = compose
        const last = children[children.length - 1]
        children.delete(last)
        poly = null
      }

      function crtTrack(obj) {
        const { pointSize } = obj
        const track = new Track(obj)
        track.start = new Date()
        track.timeLen = 2000
        track.loop = true
        track.keyMap = new Map([
          [
            'pointSize',
            [
              [500, pointSize],
              [1000, 0],
              [1500, pointSize],
            ],
          ],
          [
            'alpha',
            [
              [500, 1],
              [1000, 0],
              [1500, 1],
            ],
          ],
        ])
        compose.add(track)
      }

      function hoverPoint(mx, my) {
        for (let { geoData } of sky.children) {
          for (let obj of geoData) {
            if (poly && obj === poly.geoData[poly.geoData.length - 1]) {
              continue
            }
            const delta = {
              x: mx - obj.x,
              y: my - obj.y,
            }
            const { x, y } = glToCssPos(delta, canvas)
            const dist = x * x + y * y
            if (dist < 100) {
              return obj
            }
          }
        }
        return null
      }

      function random() {
        return Math.random() * 8 + 3
      }

      function render() {
        gl.clear(gl.COLOR_BUFFER_BIT)
        sky.draw()
      }
    </script>
  </body>
</html>
